﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace TpFinalSimu
{
    public partial class Form1 : Form
    {
        double stCarne = 0;
        double stAlmacen = 0;
        double[] _stVerdura = new double[5];
        double stKiosco = 0;
        //double stVerdura = 0;
        public double stVerdura
        {
            get 
            {
                return _stVerdura.Sum();
            }
        }


        int fechaLlegadaCarne = 1;
        int fechaLlegadaVerdura = 1;
        int fechaLlegadaAlmacen = 1;
        int fechaLlegadaKiosco = 1;

        int vtasEnsaladasTot = 0;
        int vtasTartasTot = 0;
        int vtasMenuTot = 0;
        double vtasKioscoTot = 0;

        int vtasEnsladasPerdidas = 0;
        int vtasTartasPerdidas = 0;
        int vtasMenuPerdidas = 0;
        double vtasKioscoPerdidas = 0;
        double verdurasDesperdiciadas = 0;

        List<double> historicoStockCarne = new List<double>();
        List<double> historicoStockVerdura = new List<double>();
        List<double> historicoStockAlmacen = new List<double>();
        List<double> historicoStockKiosco = new List<double>();

        List<double> historicoVentasEnsaladas = new List<double>();
        List<double> historicoVentasMenues = new List<double>();
        List<double> historicoVentasTartas = new List<double>();
        List<double> historicoVentasTotEnsaladas = new List<double>();
        List<double> historicoVentasTotMenues = new List<double>();
        List<double> historicoVentasTotTartas = new List<double>();

        double costoAcum = 0;

        int cantSimu;
        double TPCarne;
        double TPVerdura;
        double TPAlmacen;
        double TPKiosco;
        double CostoPedidoKiosco;
        double SRCarne;
        double SRVerdura;
        double SRAlmacen;
        double SRKiosco;

        int tiempoEyRCarne = 10;
        int tiempoEyRVerdura = 20;
        int tiempoEyRAlmacen = 20;
        int tiempoEyRKiosco = 15;
        int tiempoTotEyR = 0;
        int cantPedidosVerdura = 0;
        int cantVtasPerdidasPorAlmacen = 0;
        int cantVtasPerdidasPorVerdura = 0;
        int cantVtasPerdidasPorCarne = 0;

        public Form1()
        {
            InitializeComponent();
        }

        public void ReiniciarSimulacion()
        {
            historicoStockCarne = new List<double>();
            historicoStockVerdura = new List<double>();
            historicoStockAlmacen = new List<double>();
            historicoStockKiosco = new List<double>();

            historicoVentasEnsaladas = new List<double>();
            historicoVentasMenues = new List<double>();
            historicoVentasTartas = new List<double>();
            historicoVentasTotEnsaladas = new List<double>();
            historicoVentasTotMenues = new List<double>();
            historicoVentasTotTartas = new List<double>();

            stCarne = 0;
            stAlmacen = 0;
            for (int i = 0; i <= 4; i++)
                _stVerdura[i] = 0;
            //stVerdura = 0;

            stKiosco = 0;

            fechaLlegadaCarne = 1;
            fechaLlegadaVerdura = 1;
            fechaLlegadaAlmacen = 1;
            fechaLlegadaKiosco = 1;

            vtasEnsaladasTot = 0;
            vtasTartasTot = 0;
            vtasMenuTot = 0;
            vtasKioscoTot = 0;

            vtasEnsladasPerdidas = 0;
            vtasTartasPerdidas = 0;
            vtasMenuPerdidas = 0;
            vtasKioscoPerdidas = 0;

            cantVtasPerdidasPorCarne = 0;
            cantVtasPerdidasPorVerdura = 0;
            cantVtasPerdidasPorAlmacen = 0;

            verdurasDesperdiciadas = 0;
            tiempoTotEyR = 0;

            costoAcum = 0;
            cantPedidosVerdura = 0;

            VaciarResultados();
        }


        private void label2_Click(object sender, EventArgs e)
        {

        }

        private void btnSimular_Click(object sender, EventArgs e)
        {
            ReiniciarSimulacion();

            cantSimu = Convert.ToInt32(txtCantSimu.Text);
            TPCarne = Convert.ToDouble(txtTPCarne.Text);
            TPVerdura = Convert.ToDouble(txtTPVerdura.Text);
            TPAlmacen = Convert.ToDouble(txtTPAlmacen.Text);
            TPKiosco = Convert.ToDouble(txtTPKiosco.Text) * 1.6;
            CostoPedidoKiosco = Convert.ToDouble(txtTPKiosco.Text);
            SRCarne = Convert.ToDouble(txtSRCarne.Text);
            SRVerdura = Convert.ToDouble(txtSRVerdura.Text);
            SRAlmacen = Convert.ToDouble(txtSRAlmacen.Text);
            SRKiosco = Convert.ToDouble(txtSRKiosco.Text);

            //lblErrorCarne.Visible = TPCarne + SRCarne > 200;
            //lblErrorVerdura.Visible = TPVerdura + SRVerdura > 400;
            //lblErrorAlmacen.Visible = TPAlmacen + SRAlmacen > 150;

            historicoStockCarne.Add(TPCarne);
            historicoStockVerdura.Add(TPVerdura);
            historicoStockAlmacen.Add(TPAlmacen);
            historicoStockKiosco.Add(TPKiosco);

            //stCarne = 450;
            //_stVerdura[0] = 1000;
            //stAlmacen = 170;

            if (!(lblErrorCarne.Visible || lblErrorVerdura.Visible || lblErrorAlmacen.Visible))
            {
                for (int t = 1; t <= cantSimu; t++)
                {
                    if (t % 7 == 6 || t % 7 == 0)
                    {
                        this.DesperdicioDeVerdura();

                        ActualizarHistoricos();
                    }
                    else
                    {
                        this.RecibirPedidos(t);

                        this.VentaDePlatos();

                        this.VentaDeKiosco();

                        this.DesperdicioDeVerdura();

                        this.EmitirPedidos(t);

                        ActualizarHistoricos();
                    }
                }

                this.CalcularYMostrarResultados();
            }
        }

        private void ActualizarHistoricos()
        {
            historicoStockCarne.Add(stCarne);
            historicoStockVerdura.Add(stVerdura);
            historicoStockAlmacen.Add(stAlmacen);
            historicoStockKiosco.Add(stKiosco);
        }

        private void DesperdicioDeVerdura()
        {
            //double stVerdAnt = stVerdura;
            //stVerdura = stVerdura * 0.99;
            //verdurasDesperdiciadas += stVerdAnt - stVerdura;
            double[] porcDesperdicio = new double[4];
            porcDesperdicio[0] = 0.05;
            porcDesperdicio[1] = 0.07;
            porcDesperdicio[2] = 0.1;
            porcDesperdicio[3] = 0.14;

            verdurasDesperdiciadas += _stVerdura[4];
            for (int i = 3; i >= 0; i--)
            {
                double verdRestante = Math.Round(_stVerdura[i] * (1 - porcDesperdicio[i]), 3);
                verdurasDesperdiciadas += _stVerdura[i] - verdRestante;
                _stVerdura[i] = verdRestante;
                _stVerdura[i + 1] = _stVerdura[i];
            }

            _stVerdura[0] = 0;
        }

        private void CalcularYMostrarResultados()
        {
            double ganTot = (vtasEnsaladasTot * 36 + vtasMenuTot * 34 + vtasTartasTot * 34 + vtasKioscoTot) - costoAcum - (100000*cantSimu)/30;
            lblGananciaTot.Text = "$" + ganTot.ToString("0.00");
            lblGanMensual.Text = "$" + Math.Round((ganTot * 30) / cantSimu, 2).ToString();

            double verdUsadas = vtasEnsaladasTot * 0.36 + vtasMenuTot * 0.17 + vtasTartasTot * 0.133;
            lblDesperVerd.Text = (((double)verdurasDesperdiciadas / ((double)(verdurasDesperdiciadas + verdUsadas))) * 100).ToString("0.00") + "%";

            lblPerdEns.Text = (((double)vtasEnsladasPerdidas / ((double)(vtasEnsladasPerdidas + vtasEnsaladasTot))) * 100).ToString("0.00") + "%";

            lblPerdKiosco.Text = (((double)vtasKioscoPerdidas / ((double)(vtasKioscoPerdidas + vtasKioscoTot))) * 100).ToString("0.00") + "%";

            lblPerdMenu.Text = (((double)vtasMenuPerdidas / ((double)(vtasMenuPerdidas + vtasMenuTot))) * 100).ToString("0.00") + "%";

            lblPerdTartas.Text = (((double)vtasTartasPerdidas / ((double)(vtasTartasPerdidas + vtasTartasTot))) * 100).ToString("0.00") + "%";

            lblTiempoMensEyR.Text = (tiempoTotEyR * 30 / cantSimu).ToString() + " minutos";

            lblPedidosVerdura.Text = cantPedidosVerdura.ToString();
            lblEnsTot.Text = (vtasEnsaladasTot + vtasEnsladasPerdidas).ToString();
            lblMenuTot.Text = (vtasMenuTot + vtasMenuPerdidas).ToString();
            lblTartasTot.Text = (vtasTartasTot + vtasTartasPerdidas).ToString();

            if (vtasEnsladasPerdidas + vtasMenuPerdidas + vtasTartasPerdidas > 0)
            {
                lblPerdCarne.Text = (((double)cantVtasPerdidasPorCarne / (double)(vtasEnsladasPerdidas + vtasMenuPerdidas + vtasTartasPerdidas)) * 100).ToString("0.00") + "%";
                lblPerdVerdura.Text = (((double)cantVtasPerdidasPorVerdura / (double)(vtasEnsladasPerdidas + vtasMenuPerdidas + vtasTartasPerdidas)) * 100).ToString("0.00") + "%";
                lblPerdAlmacen.Text = (((double)cantVtasPerdidasPorAlmacen / (double)(vtasEnsladasPerdidas + vtasMenuPerdidas + vtasTartasPerdidas)) * 100).ToString("0.00") + "%";
            }
        }

        private void EmitirPedidos(int t)
        {
            if (stCarne <= SRCarne && fechaLlegadaCarne <= t)
            {
                if (t % 7 == 5)
                    fechaLlegadaCarne = t + 3;
                else
                    fechaLlegadaCarne = t + 1;

                if (TPCarne <= 65)
                    costoAcum += TPCarne * 45;
                else if (TPCarne <= 110)
                    costoAcum += TPCarne * 42.75;
                else if (TPCarne <= 155)
                    costoAcum += TPCarne * 40.5;
                else
                    costoAcum += TPCarne * 38.25;

                tiempoTotEyR += tiempoEyRCarne; 
            }

            if (stVerdura <= SRVerdura && fechaLlegadaVerdura <= t)
            {
                cantPedidosVerdura++;
                if (t % 7 == 5)
                    fechaLlegadaVerdura = t + 3;
                else
                    fechaLlegadaVerdura = t + 1;

                if (TPVerdura <= 150)
                    costoAcum += TPVerdura * 20;
                else if (TPVerdura <= 250)
                    costoAcum += TPVerdura * 18;
                else if (TPVerdura <= 350)
                    costoAcum += TPVerdura * 17;
                else
                    costoAcum += TPVerdura * 16;

                tiempoTotEyR += tiempoEyRVerdura;
            }

            if (stAlmacen <= SRAlmacen && fechaLlegadaAlmacen <= t)
            {
                if (t % 7 == 5)
                    fechaLlegadaAlmacen = t + 3;
                else
                    fechaLlegadaAlmacen = t + 1;

                if (TPAlmacen <= 51)
                    costoAcum += TPAlmacen * 120;
                else if (TPAlmacen <= 69)
                    costoAcum += TPAlmacen * 114;
                else if (TPAlmacen <= 87)
                    costoAcum += TPAlmacen * 108;
                else
                    costoAcum += TPAlmacen * 102;

                tiempoTotEyR += tiempoEyRAlmacen;
            }

            if (stKiosco <= SRKiosco && fechaLlegadaKiosco <= t)
            {
                fechaLlegadaKiosco =(int)Math.Round(t + (2*GetDoubleRandom(0, 1) + 1));

                if (fechaLlegadaKiosco % 7 == 6)
                    fechaLlegadaKiosco += 2;
                if (fechaLlegadaKiosco % 7 == 0)
                    fechaLlegadaKiosco ++;

                costoAcum += CostoPedidoKiosco;
                tiempoTotEyR += tiempoEyRKiosco;
            }
        }

        private void VentaDeKiosco()
        {
            double ventaDiaria = Math.Round(800 * GetDoubleRandom(0, 1) + 3000, 2); // ver este valor

            if (stKiosco >= ventaDiaria)
            {
                stKiosco -= ventaDiaria;
                vtasKioscoTot += ventaDiaria;
            }
            else
            {
                vtasKioscoPerdidas += (ventaDiaria - stKiosco);
                vtasKioscoTot += stKiosco;
                stKiosco = 0;
            }
        }

        private void VentaDePlatos()
        {
            double tEsteDia = 0;
            double tiempoDeProxEnsalada = 0;
            double tiempoDeProxTarta = 0;
            double tiempoDeProxMenu = 0;

            int esteDiaEnsaladas = 0;
            int esteDiaMenu = 0;
            int esteDiaTartas = 0;

            int esteDiaTotalEnsaladas = 0;
            int esteDiaTotalMenu = 0;
            int esteDiaTotalTartas = 0;

            while (tEsteDia <= 300) 
            {
                if (tiempoDeProxEnsalada <= tiempoDeProxMenu && tiempoDeProxEnsalada <= tiempoDeProxTarta)
                {
                    tEsteDia = tiempoDeProxEnsalada;
                    double r =  GetDoubleRandom(0, 0.9999);
                    double iaEns = 0.39897 * Math.Pow((Math.Log(1/(1-r))),(1/3.2748)) + 0.78471;
                    tiempoDeProxEnsalada += iaEns;

                    esteDiaTotalEnsaladas++;

                    if (HayStock(0.045, 0.36, 0.045))
                    {
                        stCarne -= 0.045;
                        DisminuirStockDeVerdura(0.36);
                        stAlmacen -= 0.045;

                        vtasEnsaladasTot++;
                        esteDiaEnsaladas++;
                    }
                    else
                        vtasEnsladasPerdidas++;
            
                }
                else if (tiempoDeProxMenu <= tiempoDeProxEnsalada && tiempoDeProxMenu <= tiempoDeProxTarta)
                {
                    tEsteDia = tiempoDeProxMenu;
                    double r = GetDoubleRandom(0, 0.9999);
                    double iaMenu = 3.8506 * Math.Pow((Math.Log(1 / (1 - r))), (1 / 1.5978)) + 4.8507;
                    tiempoDeProxMenu += iaMenu;

                    esteDiaTotalMenu++;

                    if (HayStock(0.2125, 0.170, 0.0425))
                    {
                        stCarne -= 0.2125;
                        DisminuirStockDeVerdura(0.170);
                        stAlmacen -= 0.0425;

                        vtasMenuTot++;
                        esteDiaMenu++;
                    }
                    else
                        vtasMenuPerdidas++;
                }
                else
                {
                    tEsteDia = tiempoDeProxTarta;
                    double r = GetDoubleRandom(0, 0.9999);
                    double iaTarta = 2 * 2.2203 * Math.Log(1/(1-r)) + 6.5028;
                    tiempoDeProxTarta += iaTarta;

                    esteDiaTotalTartas++;

                    if (HayStock(0.095, 0.133, 0.152))
                    {
                        stCarne -= 0.095;
                        DisminuirStockDeVerdura(0.133);
                        stAlmacen -= 0.152;

                        vtasTartasTot++;
                        esteDiaTartas++;
                    }
                    else
                        vtasTartasPerdidas++;
                }
            }

            historicoVentasEnsaladas.Add(esteDiaEnsaladas);
            historicoVentasMenues.Add(esteDiaMenu);
            historicoVentasTartas.Add(esteDiaTartas);

            historicoVentasTotEnsaladas.Add(esteDiaTotalEnsaladas);
            historicoVentasTotMenues.Add(esteDiaTotalMenu);
            historicoVentasTotTartas.Add(esteDiaTotalTartas);
        }

        private void DisminuirStockDeVerdura(double p)
        {
            //stVerdura -= p;
            for (int i = 4; i >= 0; i--)
            {
                if (_stVerdura[i] < p)
                {
                    p -= _stVerdura[i];
                    _stVerdura[i] = 0;
                }
                else
                {
                    _stVerdura[i] -= p;
                    return;
                }
             
            }
        }

        private bool HayStock(double cantCarne, double cantVerdura, double cantAlmacen)
        {
            bool hayStock = true;

            if (stCarne < cantCarne)
            {
                hayStock = false;
                cantVtasPerdidasPorCarne++;
            }
                

            if (stVerdura < cantVerdura)
            {
                hayStock = false;
                cantVtasPerdidasPorVerdura++;
            }

            if (stAlmacen < cantAlmacen)
            {
                hayStock = false;
                cantVtasPerdidasPorAlmacen++;
            }

            return hayStock;

        }

        public int GetRandom(int min, int max)
        {
            Random rnd = new Random();
            return rnd.Next(min, max);
        }

        public double GetDoubleRandom(double min, double max)
        {
            Random random = new Random();
            return Math.Round(random.NextDouble() * (max - min) + min, 4, MidpointRounding.AwayFromZero); 
        }

        private void RecibirPedidos(int t)
        {
            if (t == fechaLlegadaCarne)
                stCarne += TPCarne;

            if (t == fechaLlegadaVerdura)
                _stVerdura[0] = TPVerdura;
                //stVerdura += TPVerdura;

            if (t == fechaLlegadaAlmacen)
                stAlmacen += TPAlmacen;

            if (t == fechaLlegadaKiosco)
                stKiosco += TPKiosco;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            ReiniciarSimulacion();
            txtCantSimu.Text = string.Empty;
            txtSRAlmacen.Text = string.Empty;
            txtSRCarne.Text = string.Empty;
            txtSRKiosco.Text = string.Empty;
            txtSRKiosco.Text = string.Empty;
            txtSRVerdura.Text = string.Empty;
            txtTPAlmacen.Text = string.Empty;
            txtTPCarne.Text = string.Empty; 
            txtTPKiosco.Text = string.Empty;
            txtTPVerdura.Text = string.Empty;            
            
        }

        private void lblDesperVerd_Click(object sender, EventArgs e)
        {
            
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            VaciarResultados();
        }

        private void VaciarResultados()
        {
            lblGananciaTot.Text = string.Empty;
            lblGanMensual.Text = string.Empty;
            lblDesperVerd.Text = string.Empty;
            lblPerdEns.Text = string.Empty;
            lblPerdKiosco.Text = string.Empty;
            lblPerdMenu.Text = string.Empty;
            lblPerdTartas.Text = string.Empty;
            lblTiempoMensEyR.Text = string.Empty;
            lblPerdAlmacen.Text = string.Empty;
            lblPerdCarne.Text = string.Empty;
            lblPerdVerdura.Text = string.Empty;
        }
    }
}
